define(['ash', 'json!game/data/UpgradeData.json', 'game/constants/PlayerActionConstants', 'game/constants/WorldConstants', 'game/vos/UpgradeVO'],
	function (Ash, UpgradeData, PlayerActionConstants, WorldConstants, UpgradeVO) {

		let UpgradeConstants = {

			BLUEPRINT_BRACKET_EARLY: "b-early",
			BLUEPRINT_BRACKET_LATE: "b-late",

			UPGRADE_TYPE_RUMOURS: "rumours",
			UPGRADE_TYPE_HOPE: "hope",
			UPGRADE_TYPE_EVIDENCE: "evidence",
			UPGRADE_TYPE_INSIGHT: "insight",

			upgradeStatus: {
				HIDDEN: "HIDDEN",
				BLUEPRINT_IN_PROGRESS: "BLUEPRINT_IN_PROGRESS",
				BLUEPRINT_USABLE: "BLUEPRINT_USABLE",
				VISIBLE_HINT: "VISIBLE_HINT",
				VISIBLE_FULL: "VISIBLE_FULL",
				UNLOCKABLE: "UNLOCKABLE",
				UNLOCKED: "UNLOCKED",
			},

			upgradeDefinitions: {},

			upgradeUIEffects: {
				calendar: "calendar",
			},

			unlockingUpgradesByWorker: {},
			unlockingUpgradesByUIEffect: {},
			improvingUpgradesByImprovement: {},
			improvingUpgradesByWorker: {},
			improvingUpgradesByEvent: {},

			// camp ordinal > a list of blueprints, first array is early, second is late, third is blueprints that can appear on campless levels
			blueprintsByCampOrdinal: {},

			upgradeDescriptions: {
				unlock_item_clothing_body_15: "强化服装，能够承受最恶劣的环境。",
				unlock_item_clothing_over_15: "现代盔甲，灵感来自军事自动机。",
				unlock_item_weapon_15: "制造最致命武器的知识。",
				unlock_building_spaceship1: "一个能够离开这个星球并飞行很远的殖民飞船船体设计图。",
				unlock_building_spaceship2: "殖民飞船的护盾，能够保护它免受太空危险。",
				unlock_building_spaceship3: "支持殖民飞船上长时间生命维持的技术。",
				unlock_item_bag_4: "皮革工艺，用于制作更好的袋子。",
				improve_building_market3: "部分恢复传说中曾覆盖整个城市的网络。",
				improve_building_cementmill: "新型水泥混合物用于更坚固的混凝土。",
				unlock_building_researchcenter: "一个能够产生新知识的地方，而不仅仅是收集和存档旧知识。",
				unlock_item_weapon_14: "将武器和战斗带到一个新的破坏性水平。",
				unlock_item_clothing_head_5: "制作高端头盔的艺术。",
				improve_building_apothecary: "重新发现的现代技术用于疾病预防和治疗。",
				unlock_item_weapon_13: "解锁一种新的致命武器类别。",
				unlock_building_radio: "建造广播塔以增加文明的声誉。",
				unlock_building_robots: "建造机器人以帮助工人更高效地完成工作。",
				improve_building_hospital: "用于修复人体的复杂程序。",
				unlock_item_clothing_body_13: "更好地使用蜘蛛丝和回收材料。",
				unlock_item_weapon_12: "一种在近距离特别具有破坏性的强力火器。",
				unlock_item_scavenger_gear: "改进旧设计的新技术。",
				improve_worker_chemist_2: "重新探索物质和化学反应的研究。",
				unlock_item_clothing_upper_4: "",
				improve_building_shrine: "另一种找到问题答案的方法。",
				unlock_item_weapon_11: "改进的战斧。",
				unlock_item_clothing6: "改进现有探索服装的技术。",
				improve_building_storage2: "通过控制温度来改善存储。",
				improve_building_fortification_2: "更好的防御工事。",
				unlock_item_clothing3h: "好手套可以保护探险者。",
				unlock_item_clothing4he: "防护环境危害的装备。",
				unlock_item_bag_3: "制作更好的袋子。",
				unlock_item_weapon_10: "一种允许用户无需重新装填即可发射多发子弹的枪。",
				unlock_building_aqueduct: "利用衰退的水基础设施并扩展它以高效储存和输送水。",
				unlock_item_clothing4: "基础防护服在战斗中提供优势。",
				improve_building_library2: "一种有组织的方法来增长新知识。",
				unlock_building_apothecary: "制作草药的基础知识。",
				improve_worker_trapper_2: "通过腌制、烟熏和腌渍食物使其保鲜更长时间。",
				unlock_building_barracks: "专门训练的工人类以保护营地。",
				improve_building_campfire_1: "将篝火变成定居点的骄傲。",
				improve_building_inn: "另一种提升士气和团结团队的有用方法。",
				improve_building_market2: "通过使用更轻便的货币进一步改善贸易，使其更容易携带。",
				unlock_item_weapon_8: "改进的金属加工技术允许更好的武器和更多的工具。",
				unlock_item_clothing5: "利用新的金属加工技术进行防护。",
				unlock_item_clothing3: "提供基础防护的标准化服装。",
				improve_building_stable: "管理更大的商队，可以携带更多货物。",
				unlock_item_clothing_hands_25: "手套是清道夫的最佳工具。",
				improve_building_storage1: "阻止其他动物接近食物和材料，以更可靠的方式存储。",
				unlock_building_passage_hole: "在没有现有楼梯或电梯的情况下，建造通道以连接楼层。",
				unlock_building_house2: "重新利用塔楼，可以容纳更多人。",
				unlock_building_smithy: "铁匠可以将废金属变成工具和武器。",
				unlock_item_bag_2: "为探险者制作更好的袋子。",
				unlock_item_weapon_6: "一种用相当简单的材料制成的致命远程武器。",
				unlock_item_firstaid: "随时治愈伤口。",
				improve_building_market: "通用交换媒介使交易更高效。",
				improve_worker_water_2: "大规模过滤和消毒饮用水的技术，允许使用更多水源。",
				unlock_building_cementmill: "解锁混凝土的生产，这是一种强大且多用途的建筑材料。",
				unlock_item_clothing4h: "创造和操控新的、更强的纤维，提供更好的防护和更容易的制造。",
				unlock_building_passage_elevator: "修复电梯，使其允许通向新的楼层。",
				unlock_item_weapon_5: "一件为战争制造的武器。",
				unlock_building_bridge: "在坍塌的区域上建造桥梁。",
				improve_building_library: "一种更系统的方法来收集和保存知识。将来会启用更多专门化工人。",
				unlock_building_lights: "照亮营地的灯光，彻底驱散黑暗。",
				unlock_item_weapon_4: "一种古老但有效的武器。",
				improve_worker_scavenger_2: "处理技术允许回收以前居民留下的更多金属。",
				improve_worker_scavenger_4: "利用以前文明留下的最先进材料。",
				unlock_building_stable: "到其他派系交易商品。",
				unlock_building_library: "集中力量建立和存储知识。",
				unlock_building_inn: "有时旅客经过营地。也许我们可以为他们提供一个睡觉的地方？",
				unlock_building_market: "与外国营地和合作社进行贸易。",
				unlock_building_fortifications: "用于防止不受欢迎的陌生人的建设。",
				unlock_building_fortifications2: "建立更好的防御工事。",
				unlock_item_bag_1: "制作耐用皮革制品的艺术。",
				unlock_item_weapon_2: "稍微比自制刀更可靠。",
				unlock_clothing_basic: "制作基础服装的技术。",
				unlock_clothing_warm: "制造纺织品的新方法。",
				unlock_building_darkfarm: "替代的食物来源。",
				unlock_building_tradingpost: "在营地之间建立基本的贸易路线，允许他们共享资源。",
				unlock_item_clothing2: "用织物制作衣服的技艺。",
				unlock_building_passage_staircase: "管理大型建筑项目，并建造允许不同楼层之间通行的结构。",
				unlock_building_hospital: "治疗基本伤害。",
				unlock_worker_rope: "使用收集的纤维和布料制作绳索，这是一种有用的建筑和制作材料。",
				unlock_item_shoe1: "使用随手可得的材料制作有用物品的技能。",
				unlock_action_clear_waste_r: "允许清除环境中的一些放射性废物。",
				unlock_action_clear_waste_t: "允许清除环境中的一些有毒废物。",
				improve_building_temple2: "或许灵魂会欣赏食物、珠宝、骨头、植物或衣物的祭品？",
				improve_building_temple3: "将寺庙扩展为任何人都可以来冥想的地方。",
				unlock_building_greenhouse: "在城市生产更多食物的方法。",
				unlock_item_clothingl14: "防护辐射环境的衣物。",
				unlock_building_beacon: "城市中的灯光熄灭，使探索变得不那么危险。",
				improve_building_campfire_2: "将营火改造成整个定居点的聚集地。",
				unlock_building_square: "营造一个放松和社交的空间。",
				unlock_item_clothing_head_27: "用皮革制作更多的东西。",
				improve_building_collector_water_2: "改进水桶，收集更多的水。",
				improve_building_stable_2: "通过携带更多驮畜来提高车队容量",
				improve_building_collector_food_2: "改进陷阱，这样它们就可以收集更多的食物。",
				unlock_building_generator: "建造简单的发电机，为定居点供电，提高整体生活质量。",
				improve_worker_cleric_2: "通过共享仪式使社区更紧密地联系在一起",
				improve_worker_cleric_3: "使用经文来存储有关灵魂的知识，并允许神职人员维护他们的权威。",
				improve_worker_gardener_2: "开发不同的草药品种，以便在新条件下更好地生存",
				improve_worker_gardener_3: "自动化灌溉系统提高温室产量",
				improve_worker_rubber_2: "更好的橡胶生产加工技术",
				improve_worker_rubber_3: "一种新型橡胶，生产更快",
				improve_building_barracks_3: "在营房内建立更多角色，以保持高效运行",
				improve_worker_scavenger_3: "进一步的工艺清除了金属，使以前无法加工的金属再次可用",
				improve_worker_smith_2: "改进金属加工技术，让工具匠更有效地工作",
				improve_worker_smith_3: "模块化是大规模生产的基础",
				improve_worker_trapper_3: "加工食品的使用寿命更长，能够使用其他过于令人不快的成分，最终提高捕猎者的效率",
				improve_worker_water_3: "从收集的所有水中获得更多",
				unlock_project_tradingpost_connector: "一个巨大的电梯，横跨整个楼层，允许交易员绕过整个危险环境。",
				improve_building_hospital_3: "减少医院就诊的创伤，并启用新的植入物。",
				improve_worker_chemist_3: "进一步优化燃料生产",
				improve_building_radiotower: "改进广播电台，远距离发送信息",
				improve_building_robots: "改进机器人工厂，生产更多的机器人。",
				improve_worker_scientist: "为图书馆添加专用工作空间",
				improve_building_house2: "建造更高的塔楼，为更多的人提供空间",
				improve_worker_chemist_4: "进一步提高燃料产量",
				improve_worker_smith_4: "优化工具生产",
			},

			piecesByBlueprint: {},

			// caches for faster world generation / page load
			campOrdinalsByBlueprint: {},
			minCampOrdinalsByUpgrade: {},
			minimumCampOrdinalForUpgrade: {},

			loadData: function (data) {
				for (upgradeID in data) {
					this.loadUpgradeData(data[upgradeID])
				}
			},

			loadUpgradeData: function (def) {
				let addUpgradeEffectToList = function (dict, key, upgradeID) {
					if (!dict[key]) dict[key] = [];
					dict[key].push(upgradeID);
				};
				let desc = UpgradeConstants.upgradeDescriptions[def.id];
				if (!desc) {
					log.w("未找到有关升级 ID 的描述: " + def.id);
				}
				UpgradeConstants.upgradeDefinitions[def.id] = new UpgradeVO(def.id, def.name, desc);
				UpgradeConstants.upgradeDefinitions[def.id].campOrdinal = def.campOrdinal;

				if (def.blueprintPieces) {
					UpgradeConstants.piecesByBlueprint[def.id] = def.blueprintPieces;

					if (!UpgradeConstants.blueprintsByCampOrdinal[def.blueprintCampOrdinal])
						UpgradeConstants.blueprintsByCampOrdinal[def.blueprintCampOrdinal] = [[], [], []];
					let index = def.blueprintIsCampless ? 2 : def.blueprintIsEarly ? 0 : 1;
					UpgradeConstants.blueprintsByCampOrdinal[def.blueprintCampOrdinal][index].push(def.id);
				}

				if (def.effects) {
					if (def.effects.unlocksWorker) {
						UpgradeConstants.unlockingUpgradesByWorker[def.effects.unlocksWorker] = def.id;
					}
					if (def.effects.improvesBuildings) {
						let buildings = def.effects.improvesBuildings.split(" ");
						for (let i = 0; i < buildings.length; i++) {
							let building = buildings[i];
							if (building.length < 2) continue;
							addUpgradeEffectToList(UpgradeConstants.improvingUpgradesByImprovement, building, def.id);
						}
					}
					if (def.effects.improvesWorker) {
						addUpgradeEffectToList(UpgradeConstants.improvingUpgradesByWorker, def.effects.improvesWorker, def.id);
					}
					if (def.effects.unlocksUI) {
						UpgradeConstants.unlockingUpgradesByUIEffect[def.effects.unlocksUI] = def.id;
					}
					if (def.effects.improvesOccurrence) {
						let occurrence = def.effects.improvesOccurrence.replaceAll("+", "");
						addUpgradeEffectToList(UpgradeConstants.improvingUpgradesByEvent, occurrence, def.id);
					}
				}
			},

			getBlueprintCampOrdinal: function (upgradeID) {
				if (this.campOrdinalsByBlueprint[upgradeID]) {
					return this.campOrdinalsByBlueprint[upgradeID];
				}
				for (var key in this.blueprintsByCampOrdinal) {
					for (let i = 0; i < 3; i++) {
						if (this.blueprintsByCampOrdinal[key][i].indexOf(upgradeID) >= 0) {
							this.campOrdinalsByBlueprint[upgradeID] = key;
							return key;
						}
					}
				}
				return 1;
			},

			getMaxPiecesForBlueprint: function (upgradeID) {
				if (this.piecesByBlueprint[upgradeID]) return this.piecesByBlueprint[upgradeID];
				return 3;
			},

			getBlueprintBracket: function (upgradeID) {
				var ordinal = this.getBlueprintCampOrdinal(upgradeID);
				if (this.blueprintsByCampOrdinal[ordinal][0].indexOf(upgradeID) >= 0) return this.BLUEPRINT_BRACKET_EARLY;
				if (this.blueprintsByCampOrdinal[ordinal][1].indexOf(upgradeID) >= 0) return this.BLUEPRINT_BRACKET_LATE;
				if (this.blueprintsByCampOrdinal[ordinal][2].indexOf(upgradeID) >= 0) return this.BLUEPRINT_BRACKET_LATE;
				return null;
			},

			getUpgradeType: function (upgradeID) {
				let costs = PlayerActionConstants.costs[upgradeID] || {};
				let type = UpgradeConstants.UPGRADE_TYPE_RUMOURS;
				if (costs.insight > 0) type = UpgradeConstants.UPGRADE_TYPE_INSIGHT;
				if (costs.hope > 0) type = UpgradeConstants.UPGRADE_TYPE_HOPE;
				else if (costs.evidence > 0) type = UpgradeConstants.UPGRADE_TYPE_EVIDENCE;
				return type;
			},

			getBlueprintsByCampOrdinal: function (campOrdinal, blueprintType, levelIndex, maxLevelIndex) {
				if (!this.blueprintsByCampOrdinal[campOrdinal]) return [];
				let result = [];

				if (blueprintType == this.BLUEPRINT_BRACKET_EARLY || !blueprintType) {
					if (levelIndex == 0 || levelIndex == undefined) {
						result = result.concat(this.blueprintsByCampOrdinal[campOrdinal][0]);
					}
				}
				if (blueprintType == this.BLUEPRINT_BRACKET_LATE || !blueprintType) {
					if (levelIndex == 0 || levelIndex == undefined) {
						result = result.concat(this.blueprintsByCampOrdinal[campOrdinal][1]);
					}

					if (levelIndex == 1 || maxLevelIndex < 1 || levelIndex == undefined) {
						result = result.concat(this.blueprintsByCampOrdinal[campOrdinal][2]);
					}
				}

				return result;
			},

			getPiecesByCampOrdinal: function (campOrdinal, blueprintType, levelIndex, maxLevelIndex) {
				var pieceCount = 0;
				var blueprints = this.getBlueprintsByCampOrdinal(campOrdinal, blueprintType, levelIndex, maxLevelIndex);
				for (let i = 0; i < blueprints.length; i++) {
					pieceCount += this.getMaxPiecesForBlueprint(blueprints[i]);
				}
				return pieceCount;
			},

			getRequiredTech: function (upgradeID) {
				var reqs = PlayerActionConstants.requirements[upgradeID];
				if (reqs && reqs.upgrades) {
					return Object.keys(reqs.upgrades);
				}
				return [];
			},

			getRequiredTechAll: function (upgradeID) {
				let result = [];
				let direct = this.getRequiredTech(upgradeID);
				for (let i = 0; i < direct.length; i++) {
					result.push(direct[i])
					let indirect = this.getRequiredTechAll(direct[i]);
					for (let j = 0; j < indirect.length; j++) {
						result.push(indirect[j]);
					}
				}
				return result;
			},

			getUnlockedTech: function (upgradeID) {
				let result = [];
				for (let otherID in UpgradeConstants.upgradeDefinitions) {
					let requiredTech = this.getRequiredTech(otherID);
					if (requiredTech.indexOf(upgradeID) >= 0) {
						result.push(otherID);
					}
				}
				return result;
			},

			getAllUpgradesRequiringInsight: function () {
				if (this.allUpgradesRequiringInsight) return this.allUpgradesRequiringInsight;

				let result = [];

				for (let upgradeID in UpgradeConstants.upgradeDefinitions) {
					let costs = PlayerActionConstants.costs[upgradeID] || {};
					if (costs.insight > 0) {
						result.push(upgradeID);
					}
				}

				this.allUpgradesRequiringInsight = result;

				return result;
			},

		};

		UpgradeConstants.loadData(UpgradeData);

		return UpgradeConstants;

	});
